package com.torry.edss.domain.accessor.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.torry.edss.infras.entity.HisDailyLineDO;
import com.torry.edss.domain.model.HisDailyLine;
import com.torry.edss.infras.mapper.DailyLineMapper;
import com.torry.edss.domain.accessor.HisDailyLineAccessor;
import com.torry.edss.infras.util.DateUtil;
import com.torry.edss.integration.facade.result.FetchDailyLineResult;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import com.torry.boot.starter.mybatisplus.service.AccessorImpl;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author torry.wang
 * @since 2025-05-11
 */
@Service
@SuppressWarnings("DuplicatedCode")
public class HisDailyLineAccessorImpl extends AccessorImpl<DailyLineMapper, HisDailyLineDO, HisDailyLine> implements HisDailyLineAccessor {
    @Override
    public HisDailyLine toModel(HisDailyLineDO entity) {
        if (entity == null) return null;
        HisDailyLine hisDailyLine = new HisDailyLine();
        hisDailyLine.setCode(entity.getCode());
        hisDailyLine.setDate(entity.getDate());
        hisDailyLine.setOpen(entity.getOpen());
        hisDailyLine.setClose(entity.getClose());
        hisDailyLine.setHigh(entity.getHigh());
        hisDailyLine.setLow(entity.getLow());
        hisDailyLine.setVolume(entity.getVolume());
        hisDailyLine.setAmount(entity.getAmount());
        hisDailyLine.setUpPercentage(entity.getUpPercentage());
        hisDailyLine.setUpValue(entity.getUpValue());
        hisDailyLine.setId(entity.getId());
        hisDailyLine.setCreateTime(entity.getCreateTime());
        hisDailyLine.setUpdateTime(entity.getUpdateTime());
        return hisDailyLine;
    }

    @Override
    public HisDailyLineDO toEntity(HisDailyLine model) {
        if (model == null) return null;
        HisDailyLineDO hisDailyLineDO = new HisDailyLineDO();
        hisDailyLineDO.setCode(model.getCode());
        hisDailyLineDO.setDate(model.getDate());
        hisDailyLineDO.setOpen(model.getOpen());
        hisDailyLineDO.setClose(model.getClose());
        hisDailyLineDO.setHigh(model.getHigh());
        hisDailyLineDO.setLow(model.getLow());
        hisDailyLineDO.setVolume(model.getVolume());
        hisDailyLineDO.setAmount(model.getAmount());
        hisDailyLineDO.setUpPercentage(model.getUpPercentage());
        hisDailyLineDO.setUpValue(model.getUpValue());
        hisDailyLineDO.setId(model.getId());
        hisDailyLineDO.setCreateTime(model.getCreateTime());
        hisDailyLineDO.setUpdateTime(model.getUpdateTime());
        return hisDailyLineDO;
    }

    @Override
    public HisDailyLine getPreviousDayLine(String code, String date) {
        List<HisDailyLine> list = this.list(new LambdaQueryWrapper<HisDailyLineDO>()
                .eq(HisDailyLineDO::getCode, code)
                .lt(HisDailyLineDO::getDate, date)
                .orderByDesc(HisDailyLineDO::getDate)
                .last(" limit 1"));
        return CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
    }

    @Override
    public HisDailyLine getNextDayLine(String code, String date) {
        List<HisDailyLine> list = this.list(new LambdaQueryWrapper<HisDailyLineDO>()
                .eq(HisDailyLineDO::getCode, code)
                .gt(HisDailyLineDO::getDate, date)
                .orderByAsc(HisDailyLineDO::getDate)
                .last(" limit 1"));
        return CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
    }

    @Override
    public HisDailyLine getDayLine(String code, String date) {
        return this.getOne(new LambdaQueryWrapper<HisDailyLineDO>()
                .eq(HisDailyLineDO::getCode, code)
                .eq(HisDailyLineDO::getDate, date));
    }


    public LoadingCache<String, List<HisDailyLine>> allKinesCache = CacheBuilder.newBuilder()
            .maximumSize(3000)
            .expireAfterWrite(10, TimeUnit.SECONDS)
            .build(new CacheLoader<String, List<HisDailyLine>>() {
                @Override
                public List<HisDailyLine> load(String code) {
                    return list(new LambdaQueryWrapper<HisDailyLineDO>()
                            .eq(HisDailyLineDO::getCode, code)
                            .orderByAsc(HisDailyLineDO::getDate));
                }
            });

    @Override
    public List<HisDailyLine> findAllDayLines(String code) {
        return allKinesCache.getUnchecked(code);
    }

    @Override
    public List<HisDailyLine> findAllDayLines(String code, List<String> dates) {
        return allKinesCache.getUnchecked(code).stream().filter(e -> dates.contains(DateUtil.formatDate(e.getDate()))).collect(Collectors.toList());
    }
}
